import { HttpException, HttpStatus, Injectable } from '@nestjs/common';
import { CreateArticleDto } from './dto/create-article.dto';
import { UpdateArticleDto } from './dto/update-article.dto';
import { LikeArticleDto } from './dto/like-article.dto';
import { CommentArticleDto } from './dto/comment-article.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Article } from './entities/article.entity';
import { ArticleLike } from './entities/article-like.entity';
import { ArticleComment } from './entities/article-comment.entity';
import { Repository } from 'typeorm';
import { UserService } from '../user/user.service';
import { PaginationService } from '../../common/pagination/pagination.service';
import { Classification } from '../classification/entities/classification.entity';
import { Tag } from '../tag/entities/tag.entity';

@Injectable()
export class ArticleService {
  constructor(
    @InjectRepository(Article)
    private readonly articleRepository: Repository<Article>,
    @InjectRepository(ArticleLike)
    private readonly articleLikeRepository: Repository<ArticleLike>,
    @InjectRepository(ArticleComment)
    private readonly articleCommentRepository: Repository<ArticleComment>,
    @InjectRepository(Classification)
    private readonly classificationRepository: Repository<Classification>,
    @InjectRepository(Tag)
    private readonly tagRepository: Repository<Tag>,
    private readonly pageService: PaginationService<Article>,
    private readonly userService: UserService,
  ) {
    this.pageService = new PaginationService<Article>(this.articleRepository);
  }

  // 创建文章
  async create(createArticleDto: CreateArticleDto) {
    const { classificationId, tags, ...articleData } = createArticleDto;

    // 查找分类
    const classification = await this.classificationRepository.findOne({
      where: { id: classificationId },
    });
    if (!classification) {
      throw new HttpException('分类不存在', HttpStatus.BAD_REQUEST);
    }

    // 查找标签列表
    const tagsList = await this.tagRepository
      .createQueryBuilder('tag')
      .where('tag.id IN (:...tags)', { tags })
      .getMany();
    // console.log('查找标签-tagsList', tagsList);
    if (tagsList.length !== tags.length) {
      throw new HttpException('部分标签不存在', HttpStatus.BAD_REQUEST);
    }

    // 创建文章并关联分类表、标签表对象
    const article = this.articleRepository.create({
      ...articleData,
      classification,
      tags: tagsList,
    });

    // 保存至数据库
    return await this.articleRepository.save(article);
  }

  // 分页查询文章列表
  async findAll(params: {
    page: number;
    pageSize: number;
    title: string;
    keywords: string;
    classificationId: string;
    sortReadNum?: string;
    sortLikeNum?: string;
    sortCommentNum?: string;
  }) {
    const {
      page,
      pageSize,
      title,
      keywords,
      classificationId,
      sortCommentNum,
      sortLikeNum,
      sortReadNum,
    } = params;
    // 定义查询构造器（连classification、tag表查询）
    const qb = this.articleRepository
      .createQueryBuilder('article')
      .leftJoinAndSelect('article.classification', 'classification')
      .leftJoinAndSelect('article.tags', 'tags');

    // 只选择 classification,tag 表 的 id 和 name 字段
    qb.select([
      'article',
      'classification.id',
      'classification.name',
      'tags.id',
      'tags.name',
    ]);

    // 查询状态为1，2的数据
    qb.andWhere('article.status in (:...status)', { status: [1, 2] });

    // 模糊查询title、keywords
    title && qb.andWhere('article.title like :title', { title: `%${title}%` });

    if (keywords) {
      qb.andWhere('article.keywords like :keywords', {
        keywords: `%${keywords}%`,
      });
    }
    // 根据分类ID查询
    if (classificationId) {
      qb.andWhere('classification.id = :classificationId', {
        classificationId,
      });
    }
    // 排序
    const orderMap: { [key: string]: 'ASC' | 'DESC' } = {
      'article.isTop': 'DESC', // 是否置顶，1置顶，0不置顶，ASC升序，DESC降序
    };
    if (sortLikeNum) {
      orderMap['article.likeNum'] = this.getOrderVal(sortLikeNum);
    }
    if (sortReadNum) {
      orderMap['article.readNum'] = this.getOrderVal(sortReadNum);
    }
    if (sortCommentNum) {
      orderMap['article.commentNum'] = this.getOrderVal(sortCommentNum);
    }
    qb.orderBy(orderMap);
    // console.log('pageSearch params', params);
    // 分页查询
    return this.pageService.pageSearch({
      page,
      pageSize,
      queryBuilder: qb,
    });
  }

  async findOne(id: string) {
    return await this.articleRepository.findOne({
      where: { id, status: 1 },
      relations: { classification: true, tags: true },
    });
  }

  async update(id: string, updateArticleDto: UpdateArticleDto) {
    const data = await this.findOne(id);
    if (!data) throw new HttpException('数据不存在', HttpStatus.BAD_REQUEST);
    const updateData = this.articleRepository.merge(data, updateArticleDto);
    return await this.articleRepository.save(updateData);
  }

  async remove(id: string) {
    const data = await this.findOne(id);
    if (!data) throw new HttpException('数据不存在', HttpStatus.BAD_REQUEST);
    // return await this.articleRepository.delete({ id }); // 硬删除
    // 软删除
    return await this.articleRepository.update(id, { status: 0 });
  }

  private getOrderVal(value: string): 'ASC' | 'DESC' {
    return value.toLocaleUpperCase().startsWith('ASC') ? 'ASC' : 'DESC';
  }

  // 用户点赞、取消点赞
  async likeArticle(id: string, data: LikeArticleDto) {
    const { userId, like } = data;
    // 点赞的文章
    const article = await this.findOne(id);
    if (!article) throw new HttpException('数据不存在', HttpStatus.BAD_REQUEST);

    // 点赞的用户
    const user = await this.userService.findOne(userId);
    if (!user) throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);

    // 查找文章-点赞表关系
    const articleLike = await this.articleLikeRepository.findOne({
      where: { article, user },
    });

    if (like) {
      if (articleLike) {
        throw new HttpException(
          '用户已点赞，不能重复点赞',
          HttpStatus.BAD_REQUEST,
        );
      }
      const newArticleLike = this.articleLikeRepository.create({
        article,
        user,
      });
      await this.articleLikeRepository.save(newArticleLike);
      article.likeNum = article.likeNum < 0 ? 1 : article.likeNum + 1;
    } else {
      if (!articleLike) {
        throw new HttpException(
          '用户未点赞，无法取消点赞',
          HttpStatus.BAD_REQUEST,
        );
      }
      await this.articleLikeRepository.remove(articleLike);
      // 防止点赞数为负
      article.likeNum = article.likeNum < 0 ? 0 : article.likeNum - 1;
      // article.likeNum = (article.likeNum || 0) - 1;
    }

    // 更新文章点赞数量
    return await this.articleRepository.save(article);
  }

  // 文章阅读量
  async incrementReadCount(articleId: string) {
    const article = await this.findOne(articleId);
    if (!article) throw new HttpException('数据不存在', HttpStatus.BAD_REQUEST);
    article.readNum = article.readNum < 0 ? 1 : article.readNum + 1;
    // 更新文章阅读量
    return await this.articleRepository.save(article);
  }

  // 用户评论
  async commentArticle(articleId:string, data: CommentArticleDto) {
    const { userId, content } = data;
    // 查找文章
    const article = await this.findOne(articleId);
    if (!article) throw new HttpException('文章不存在', HttpStatus.BAD_REQUEST);

    // 查找用户
    const user = await this.userService.findOne(userId);
    if (!user) throw new HttpException('用户不存在', HttpStatus.BAD_REQUEST);

    // 创建评论
    const newComment = this.articleCommentRepository.create({
      content,
      user,
      article,
    });

    // 保存评论
    return await this.articleCommentRepository.save(newComment);
  }

  // 删除评论
  async deleteComment(commentId: string, userId: string) {
    // 查找评论
    const comment = await this.articleCommentRepository.findOne({
      where: { id: commentId },
      relations: ['user'],
    });
    if (!comment) throw new HttpException('评论不存在', HttpStatus.BAD_REQUEST);

    // 检查评论是否属于该用户
    if (comment.user.id !== userId) {
      throw new HttpException('无权删除他人评论', HttpStatus.FORBIDDEN);
    }

    // 删除评论
    await this.articleCommentRepository.remove(comment);
    return { message: '评论已删除' };
  }

  // 获取文章评论列表
  async getCommentsByArticle(articleId: string) {
    // 查找文章
    const article = await this.findOne(articleId);
    if (!article) throw new HttpException('文章不存在', HttpStatus.BAD_REQUEST);

    // 查找文章的所有评论
    const comments = await this.articleCommentRepository.find({
      where: { article },
      relations: ['user'],
      order: { createTime: 'DESC' },
    });

    return comments;
  }
}
